package org.ilookinto.jr;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
//import com.sun.tools.javac.util.Pair;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.log4j.Logger;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.ilookinto.doexe.Processor;
import org.ilookinto.util.CloseUtil;
import org.xml.sax.ContentHandler;

/**
 *
 * @author zwu
 */
public class MetadataListener implements EventListener {

  Session session;
  Logger _logger;
  Processor.Pair<PrintWriter, Scanner, Scanner> pair;
  String dataDir;
  boolean shutdown = false;

  public MetadataListener(Session session, final Processor.Pair<PrintWriter, Scanner, Scanner> pair, String dataDir) {
    this.session = session;
    this.pair = pair;
    this.dataDir = dataDir;
    _logger = Logger.getLogger(this.getClass());
  }

  String constructOutputFileName(String inputURL, String outputDir) {
    String fileName = null; // include the path, but not extension.
    if (outputDir.charAt(outputDir.length() - 1) != File.separatorChar) {
      outputDir += File.separatorChar;
    }
    // inputURL = inputURL.replace(uri, "");
    int indexSemicolon = inputURL.lastIndexOf("://");
    if (indexSemicolon < 0) {
      indexSemicolon = inputURL.lastIndexOf(":") + 1;
      fileName = inputURL.substring(indexSemicolon, inputURL.lastIndexOf("."));
    } else {
      fileName = inputURL.substring(indexSemicolon + 3, inputURL.lastIndexOf("."));
      int sub = fileName.indexOf(":");
      if (sub < 0) {
        sub = fileName.indexOf("/");
      }
      String[] parts = fileName.substring(0, sub).split("\\.");

      fileName = fileName.substring(sub + 1);
      for (String s : parts) {
        fileName = s + "/" + fileName;
      }
    }
    fileName = fileName.replace("//", "/");
    if ('\\' == File.separatorChar) {
      fileName = fileName.replaceAll("/", "\\\\");
    }
    if (fileName.charAt(0) == File.separatorChar) {
      fileName = fileName.substring(1);
    }
    fileName = fileName.replace(":", "_");

    String pathName = outputDir + fileName.substring(0, fileName.lastIndexOf(File.separatorChar) > 0 ? fileName.lastIndexOf(File.separatorChar) : 0);

    (new File(pathName)).mkdirs();
    _logger.info("output dir=" + pathName);
    return outputDir + fileName;
  }

  void convert(File nodeFile, String inputURL, String outputDir, String uuid) throws Exception {
    String ext = inputURL.substring(inputURL.lastIndexOf(".") + 1);
    String fileName = constructOutputFileName(inputURL, outputDir);
    String outFileNameNoExt = Text.unescape(fileName) + "-" + uuid;
    if (ext.equalsIgnoreCase("doc")
            || ext.equalsIgnoreCase("htm")
            || ext.equalsIgnoreCase("html")
            || ext.equalsIgnoreCase("mht")
            || ext.equalsIgnoreCase("docx")
            || ext.equalsIgnoreCase("txt")
            || ext.equalsIgnoreCase("rtf")) {
      String commandLine;
      //if (!ext.equalsIgnoreCase("rtf")) {
        commandLine = nodeFile.getAbsolutePath() + "$$$$" + outFileNameNoExt + ".rtf\n";
        _logger.info("command=" + commandLine);
        pair.first.write(commandLine);
        pair.first.flush();
     // }
      if (!ext.equalsIgnoreCase("html") && !ext.equalsIgnoreCase("htm") || ext.equalsIgnoreCase("mht")) {
        commandLine = nodeFile.getAbsolutePath() + "$$$$" + outFileNameNoExt + ".html\n";
        _logger.info("command=" + commandLine);
        pair.first.write(commandLine);
        pair.first.flush();
      }
      //PDF ....
      commandLine = nodeFile.getAbsolutePath() + "$$$$" + outFileNameNoExt + ".pdf\n";
      _logger.info("command=" + commandLine);
      pair.first.write(commandLine);
      pair.first.flush();

    } else if (ext.equalsIgnoreCase("pdf")) {
      File inputFile = nodeFile;
      try {
        _logger.debug("pair..exed " + pair.exeArgs[0]);
        String exePath = pair.exeArgs[0].substring(0, pair.exeArgs[0].lastIndexOf('\\')) + "\\pdf2html";
        _logger.debug("pdf2html path: " + exePath);

        ProcessBuilder pb = new ProcessBuilder(new String[]{exePath,
                  "-enc", "UTF-8", "-noframes", "-p", "-nomerge", "-nodrm", "-q",
                  inputFile.getAbsolutePath(), outFileNameNoExt + ".html"});
        Process p = pb.start();
        _logger.debug("converting pdf begin " + inputFile.getAbsolutePath());
        if (p.waitFor() != 0) {
          _logger.error("error in converting");
        } else {
          String outFile = new File(outFileNameNoExt + ".rtf").getAbsolutePath();
          String commandLine = outFileNameNoExt + ".html" + "$$$$" + outFile + "\n";
          _logger.info("command=" + commandLine);
          pair.first.write(commandLine);
          pair.first.flush();
        }
        _logger.debug("converting pdf end " + inputFile.getAbsolutePath());

      } catch (InterruptedException e) {
      } catch (IOException e) {
        _logger.error("error", e);
      } finally {
        if (inputFile != null && inputFile.exists()) {
          inputFile.delete();
        }
      }
    } else {
      MyTikaCLI.main2(new String[]{"-h", "-o=" + outFileNameNoExt + ".html", inputURL});
      pair.first.write(fileName + ".html$$$$" + outFileNameNoExt + ".rtf\n");
      pair.first.flush();
    }
  }

  public synchronized void onEvent(final EventIterator eventIterator) {
    _logger.info("Event..." + new java.util.Date());

    Future<String> result = MetadataServlet.es.submit(new EventHandler(eventIterator));
    try {
      result.get(30, TimeUnit.SECONDS);
    } catch (Exception e) {
      _logger.error("error", e);

    }
  }

  class EventHandler implements Callable {

    EventIterator eventIterator;

    EventHandler(EventIterator ei) {
      eventIterator = ei;
    }

    public String call() {
      try {
        while (eventIterator.hasNext()) {
          Event event = eventIterator.nextEvent();
          String eventPath = event.getPath();

          int eventType = event.getType();
          long time = (new java.util.Date()).getTime();
          String nodePath = eventPath.substring(1, eventPath.length());
          _logger.info("Event path = " + event.getPath());
          _logger.info("Event type= " + event.getType());

          if (eventType == Event.NODE_ADDED) {
            Node metaEntryNode = session.getRootNode().getNode(nodePath);
            _logger.info("event path= " + nodePath + ";node type=" + metaEntryNode.getPrimaryNodeType().getName());
            String uuid = metaEntryNode.getIdentifier();
            String file = nodePath;
            if (file.indexOf("/jcr:content") > 0) {
              file = file.substring(0, nodePath.indexOf("/jcr:content"));
            } else {
              continue;
            }

            File nodeFile = File.createTempFile("node", file.substring(file.lastIndexOf('.')));
            if (nodePath.endsWith("/jcr:content")) {
              InputStream is = null;
              FileOutputStream fos = new FileOutputStream(nodeFile);
              try {
                is = metaEntryNode.getProperty("jcr:data").getStream();
                IOUtils.copy(is, fos);
              } catch (Exception e) {
                _logger.error("file node", e);
              } finally {
                CloseUtil.close(is, fos);
              }
            }
            String encodedFile = URLEncoder.encode(file, "UTF-8");
            encodedFile = encodedFile.replaceAll("%2F", "/");
            encodedFile = encodedFile.replaceAll("\\+", "%20");
            String sURL = (/*uri + "/local?node=" + */encodedFile);
            _logger.info(" encodeded surl=" + sURL);
            convert(nodeFile, sURL, dataDir, uuid);
            // if (nodeFile.exists()) nodeFile.delete();
          }
        }

      } catch (Exception e) {
        _logger.debug("error", e);
        return "bad";
      }
      return "good";
    }

    private Metadata getMeta(Node node) throws Exception {
      InputStream is = node.getProperty("/jcr:data").getStream();
      ContentHandler contenthandler = new BodyContentHandler();
      Metadata metadata = new Metadata();
      metadata.set(Metadata.RESOURCE_NAME_KEY, node.getName());
      Parser parser = new AutoDetectParser();
      // OOXMLParser parser = new OOXMLParser();
      parser.parse(is, contenthandler, metadata);
      System.out.println("Mime: " + metadata.get(Metadata.CONTENT_TYPE));
      System.out.println("Title: " + metadata.get(Metadata.TITLE));
      System.out.println("Author: " + metadata.get(Metadata.AUTHOR));
      System.out.println("content: " + contenthandler.toString());
      return metadata;
    }
  }

  public static void main(String[] args) throws Exception {


    /*URL url = new URL("http://localhost:9080/ilookinto/local?node=" +  ;*/

    Processor.Pair<PrintWriter, Scanner, Scanner> pair = Processor.processing(new String[]{"C:\\zwu\\ilookinto\\J\\ilookinto\\src\\site\\WEB-INF\\resources\\2RTF"});

    pair.first.write("http://localhost:9080/ilookinto/local?node=com/cat/www/cda/files/2227148/7/M01PR10final.doc\n");
    pair.first.write("c:\\zwu\\temp\\" + "testing.rtf\n");
    //pair.second.nextLine();
    pair.first.flush();
    //pair.first.write("Q\n");

    /*
    _logger.info(new File(".").getAbsolutePath()); if(true) return;
    Repository repository = new TransientRepository(new File("data/tomcat"));
    Session session = repository.login(
    new SimpleCredentials("username", "password".toCharArray()));


    try {
    //testQueryExcept(session.getWorkspace());

    ObservationManager observationManager =
    session.getWorkspace().getObservationManager();
    observationManager.addEventListener(new MetadataListener(session),
    Event.NODE_ADDED, "/", true, null, new String[]{"nt:file"}, false);

    Node node = session.getRootNode().addNode("event");
    session.save();
    Import.importing(session.getWorkspace(), new URL("http://www.day.com/maven/jsr170/javadocs/jcr-1.0/javax/jcr/RangeIterator.html#getPosition%28%29"));
    session.save();
    //session.refresh(true);
    Thread.currentThread().sleep(9000);

    session.save();

    } catch (Exception e) {
    e.printStackTrace();
    } finally {

    session.logout();
    }
     */

  }
}
